#include "TrManager.h"
#include "TrUtils.h"
#include <QDebug>

//static std::vector<std::shared_ptr<TrObserver>>         static_gObservers;
static std::vector<TrObserver*>                         static_gObservers;
static std::unordered_map<std::string, std::string>     static_gConstructs;


inline bool update_constructs_from_conf()
{
    static_gConstructs.clear();

    std::string content;
    TrUtils::read_file_content(CONTRACTS_FILE, content);

    nJson js = nJson::parse(content);

    if (js.is_object())
    {
        for (auto& e : js.items())
        {
            std::string key = e.key();
            if (e.value().is_object())
            {
                for (auto& c : e.value().items())
                {
                    static_gConstructs.insert({ c.key(),c.value().dump(4) });
                }
            }
        }
    }
    return true;
}

Contract TrManager::get(const std::string& code)
{
    auto it = static_gConstructs.find(code);
    if (it != static_gConstructs.end())
    {
        nJson js = nJson::parse(it->second);
        if (js.is_object())
        {
            Contract contract;
            contract.m_strCode = js["code"].get<std::string>();
            contract.m_strExchg = js["exchg"].get<std::string>();
            contract.m_strName = js["name"].get<std::string>();
            contract.m_strProduct = js["product"].get<std::string>();
            contract.m_strSession = js["session"].get<std::string>();

            contract.m_maxMktQty = js["maxmarketqty"].get<uint32_t>();
            contract.m_maxLmtQty = js["maxlimitqty"].get<uint32_t>();
            contract.m_minMktQty = js["minmarketqty"].get<uint32_t>();
            contract.m_minLmtQty = js["minlimitqty"].get<uint32_t>();

            contract.m_strikePrice = js["strikeprice"].get<double>();
            contract.m_priceTick = js["pricetick"].get<double>();
            contract.m_iVolumeMultiple = js["volumemultiple"].get<int>();

            contract.m_uOpenDate = js["opendate"].get<uint32_t>();
            contract.m_uExpireDate = js["expiredate"].get<uint32_t>();

            contract.m_dLongMarginRatio = js["longmarginratio"].get<double>();
            contract.m_dShortMarginRatio = js["shortmarginratio"].get<double>();
            return contract;
        }
    }

    return Contract();
}

std::vector<std::string> TrManager::getAllSymbol()
{
    std::vector<std::string> tmp;
    for (auto itr = static_gConstructs.begin(); itr != static_gConstructs.end(); ++itr) {
        tmp.push_back(itr->first);
    }
    return tmp;
}

std::vector<std::string> TrManager::getBy(const std::string& by, const std::string& Id)
{
    std::vector<std::string> tmp;
    for (auto itr = static_gConstructs.begin(); itr != static_gConstructs.end(); ++itr) {
        nJson j = nJson::parse(itr->second);
        if (!j.is_object()) continue;

        std::string obj = j[by].get<std::string>();
        if (Id == obj)
            tmp.push_back(itr->first);
    }
    return tmp;
}

void TrManager::attach(TrObserver* observer)
{
    //static_gObservers.push_back(std::shared_ptr<TrObserver>(observer));
    auto it = std::find(static_gObservers.begin(), static_gObservers.end(), observer);
    if (it == static_gObservers.end())
    {
        //static_gObservers.push_back(std::shared_ptr<TrObserver>(observer));
        static_gObservers.push_back(observer);
    }
}

void TrManager::detach(TrObserver* observer)
{
    //auto recv_iter = std::find(static_gObservers.begin(), static_gObservers.end(), observer);
    //if (recv_iter != static_gObservers.end())
    //{
    //    static_gObservers.erase(recv_iter);
    //}
}

void TrManager::notify(TrResponseID rId, void* wParam, void* lParam)
{
    for (unsigned i = 0; i < static_gObservers.size(); ++i)
    {
        if (nullptr != static_gObservers[i])
        {
            static_gObservers[i]->OnReceive(rId, wParam, lParam);
        }
    }

    if (rId == TrResponseID::OnTdRspQryInstrumentUpdateSuccessed)
        update_constructs_from_conf();
}



TrManager::TrManager()
{
    update_constructs_from_conf();

}